﻿using System.ComponentModel;
using System.Linq;
using OpenLightGroup.Common.ApplicationServices.HealthReportingProxy;
using System;
using System.Collections.ObjectModel;
using System.Windows.Threading;

namespace OpenLightGroup.Common.ApplicationServices
{
    public class HealthReportingAgent : HealthReportingServiceClient, INotifyPropertyChanged
    {
        /// <summary>
        /// Occurs when a property value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        public event EventHandler<NewExceptionsEventArgs> LatestExceptionsChanged;
        public event EventHandler LatestEventsChanged;

        private ObservableCollection<HealthReportingEntryMetaData> _latestEvents = null;
        private ObservableCollection<HealthReportingEntryMetaData> _latestExceptions = null;

        private DispatcherTimer _timer;
        private int _numberOfLatestEvents = 25;

        public HealthReportingAgent()
        {

            this._timer = new DispatcherTimer();

            this.PollingInterval = 10;

            this._timer.Interval = TimeSpan.FromSeconds(this.PollingInterval);
            this._timer.Tick += new EventHandler(_timer_Tick);


            //ToDo does this need to be a seperate instance?
            this.GetEventsCompleted += new EventHandler<GetEventsCompletedEventArgs>(HealthReportingAgent_GetEventsCompleted);
            this.GetExceptionsCompleted += new EventHandler<GetExceptionsCompletedEventArgs>(HealthReportingAgent_GetExceptionsCompleted);
        }




        /// <summary>
        /// Gets or sets the number of latest events.
        /// </summary>
        /// <value>The number of latest events.</value>
        public int NumberOfLatestEvents
        {
            get
            {
                return _numberOfLatestEvents;
            }
            set
            {
                if (value != this._numberOfLatestEvents)
                {
                    this._numberOfLatestEvents = value;

                    if (this.PropertyChanged != null)
                        this.PropertyChanged(this, new PropertyChangedEventArgs("NumberOfLatestEvents"));
                }

            }
        }

        public ObservableCollection<HealthReportingEntryMetaData> LatestExceptions
        {
            get
            {

                if (_latestExceptions == null)
                {
                    _latestExceptions = new ObservableCollection<HealthReportingEntryMetaData>();
                }
                return _latestExceptions;

            }
        }

        public ObservableCollection<HealthReportingEntryMetaData> LatestEvents
        {
            get
            {
                if (this._latestEvents == null)
                {
                    this._latestEvents = new ObservableCollection<HealthReportingEntryMetaData>();
                }
                return this._latestEvents;
            }
        }

        /// <summary>
        /// The number of seconds between polling requests.
        /// </summary>
        public double PollingInterval
        {
            get { return this._timer.Interval.TotalSeconds; }
            set
            {
                if (value != this._timer.Interval.TotalSeconds)
                {
                    this._timer.Interval = TimeSpan.FromSeconds(value);

                    if (this.PropertyChanged != null)
                        this.PropertyChanged(this, new PropertyChangedEventArgs("PollingInterval"));
                }

            }
        }




        public void StartPolling()
        {
            this._timer.Start();
            this.RefreshLatestEntries();
        }

        public void StopPolling()
        {
            this._timer.Stop();
        }

        private void _timer_Tick(object sender, EventArgs e)
        {
            this.RefreshLatestEntries();
        }

        private void RefreshLatestEntries()
        {
            this.GetEventsAsync(0, this.NumberOfLatestEvents);
            this.GetExceptionsAsync(0, this.NumberOfLatestEvents);
        }
        private void HealthReportingAgent_GetEventsCompleted(object sender, GetEventsCompletedEventArgs e)
        {
            this.LatestEvents.Clear();
            this.LatestEvents.AddRange(e.Result);
        }

        private void HealthReportingAgent_GetExceptionsCompleted(object sender, GetExceptionsCompletedEventArgs e)
        {
            //this.LatestExceptions.Clear();
            //this.LatestExceptions.AddRange(e.Result);
            var changed = false;
            var newExceptions = 0;

            foreach (var item in e.Result)
            {
                if (this.LatestExceptions.Where(i => i.EventId == item.EventId).Count() == 0)
                {
                    this.LatestExceptions.Add(item);
                    changed = true;
                    newExceptions++;
                }
                //else
                //{
                //    this.LatestExceptions[this.LatestExceptions.IndexOf(item)] = item;
                //    changed = true;
                //}
            }

            foreach (var item in this.LatestExceptions.ToArray())
            {

               // if (!e.Result.Contains(item))
                if (e.Result.Where(i => i.EventId == item.EventId).Count() > 0)
                {
                    this.LatestExceptions.Remove(item);
                    changed = true;
                }

            }

            if ((this.LatestExceptionsChanged != null))
                this.LatestExceptionsChanged(this, new NewExceptionsEventArgs() { NewExceptions = newExceptions });

        }
    }
}